package com.fla.puzzle.utils;

import java.io.InputStream;

import com.fla.puzzle.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;

public class BitmapUtils {

    public static Bitmap createCompleted(Context context, Bitmap originalImage) {
        Bitmap bitmap = originalImage.copy(Bitmap.Config.ARGB_8888, true);

        Canvas canvas = new Canvas(bitmap);

        float itemSize = bitmap.getHeight();

        Paint p = new Paint();
        p.setColor(Color.WHITE);
        p.setAlpha(150);
        p.setTextSize(itemSize / 3.5f);
        Path path = new Path();
        path.lineTo(bitmap.getWidth(), bitmap.getHeight());
        canvas.drawTextOnPath(context.getString(R.string.completed), path, itemSize / 3, itemSize / 8, p);

        return bitmap;
    }

    /**
     * This code is courtesy of Neil Davies at http://www.inter-fuser.com
     * 
     * @param context the current context
     * @param originalImage The original Bitmap image used to create the reflection
     * @return the bitmap with a reflection
     */
    public static Bitmap createReflectedImage(Context context, Bitmap originalImage, int outputDivider) {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        // This will not scale but will flip on the Y axis
        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        // Create a Bitmap with the flip matrix applied to it.
        // We only want the bottom half of the image
        Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0, height / 2, width, height / 2, matrix, false);

        // Create a new bitmap with same width but taller to fit reflection
        Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / outputDivider), Config.ARGB_8888);

        // Create a new Canvas with the bitmap that's big enough for
        // the image plus gap plus reflection
        Canvas canvas = new Canvas(bitmapWithReflection);
        // Draw in the original image
        canvas.drawBitmap(originalImage, 0, 0, null);
        // Draw in the reflection
        canvas.drawBitmap(reflectionImage, 0, height, null);

        // Create a shader that is a linear gradient that covers the reflection
        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0, height, 0, bitmapWithReflection.getHeight(), 0x70ffffff, 0x00ffffff,
            TileMode.CLAMP);
        // Set the paint to use this shader (linear gradient)
        paint.setShader(shader);
        // Set the Transfer mode to be porter duff and destination in
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        // Draw a rectangle using the paint with our linear gradient
        canvas.drawRect(0, height, width, bitmapWithReflection.getHeight(), paint);

        return bitmapWithReflection;
    }

    public static int getScale(int originalWidth, int originalHeight, final int requiredWidth, final int requiredHeight) {
        // a scale of 1 means the original dimensions
        // of the image are maintained
        int scale = 1;

        // calculate scale only if the height or width of
        // the image exceeds the required value.
        if ((originalWidth > requiredWidth) || (originalHeight > requiredHeight)) {
            // calculate scale with respect to
            // the smaller dimension
            if (originalWidth < originalHeight)
                scale = Math.round((float) originalWidth / requiredWidth);
            else
                scale = Math.round((float) originalHeight / requiredHeight);

        }

        return scale;
    }

    public static int getSampleSize(InputStream is, int requiredWidth, int requiredHeight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        // setting inJustDecodeBounds to true
        // ensures that we are able to measure
        // the dimensions of the image,without
        // actually allocating it memory
        options.inJustDecodeBounds = true;

        // decode the file for measurement
        BitmapFactory.decodeStream(is, null, options);

        // obtain the inSampleSize for loading a
        // scaled down version of the image.
        // options.outWidth and options.outHeight
        // are the measured dimensions of the
        // original image
        return getScale(options.outWidth, options.outHeight, requiredWidth, requiredHeight);
    }
}
